import btree4j.BTreeException;
import btree4j.template.*;
import btree4j.Value;

import java.io.File;
import java.io.IOException;
import java.util.List;

public class AllTest {

    private static File dataDir = new File("test_data_all");

    public static void main(String[] args) {
        try {
            // 初始化测试环境
            if (dataDir.exists()) {
                deleteDir(dataDir); // 清理旧测试数据
            }
            dataDir.mkdirs();

            TemplateManager templateManager = new TemplateManager(dataDir);
            TemplateDataOperator dataOperator = new TemplateDataOperator(templateManager);

            // 1. 测试模板的创建、获取、更新和删除
            testTemplateOperations(templateManager);

            // 2. 测试带二级索引的模板创建和数据操作
            testSecondaryIndexOperations(templateManager, dataOperator);

            System.out.println("\n=== 所有测试通过 ===");

        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("测试失败: " + e.getMessage());
        }
    }

    private static void testTemplateOperations(TemplateManager templateManager) throws IOException, BTreeException {
        // 创建模板
        Template template1 = new Template("Users");
        template1.addColumn(new Column("id", "INT", true, false));
        template1.addColumn(new Column("name", "VARCHAR(100)", false, false));
        template1.addColumn(new Column("email", "VARCHAR(100)", false, true));
        long template1Id = templateManager.createTemplate(template1);
        System.out.println("创建模板 Users，ID: " + template1Id);

        Template template2 = new Template("Orders");
        template2.addColumn(new Column("order_id", "INT", true, false));
        template2.addColumn(new Column("user_id", "INT", false, false));
        template2.addColumn(new Column("amount", "DECIMAL(10,2)", false, false));
        template2.addColumn(new Column("status", "VARCHAR(20)", false, true));
        long template2Id = templateManager.createTemplate(template2);
        System.out.println("创建模板 Orders，ID: " + template2Id);

        // 获取模板
        Template retrievedTemplate = templateManager.getTemplate(template1Id);
        System.out.println("通过 ID 获取模板: " + retrievedTemplate);

        Template retrievedTemplateByName = templateManager.getTemplateByName("Users");
        System.out.println("通过名称获取模板: " + retrievedTemplateByName);

        // 获取所有模板
        List<Template> allTemplates = templateManager.getAllTemplates();
        System.out.println("所有模板:");
        for (Template t : allTemplates) {
            System.out.println(t);
        }

//        // 更新模板
//        if (retrievedTemplate != null) {
//            retrievedTemplate.setName("UserProfiles");
//            templateManager.updateTemplate(retrievedTemplate);
//            Template updatedTemplate = templateManager.getTemplate(template1Id);
//            System.out.println("更新后的模板: " + updatedTemplate);
//        }

        // 删除模板
        templateManager.deleteTemplate(template2Id);
        System.out.println("删除模板 Orders，ID: " + template2Id);

        // 验证模板删除
        allTemplates = templateManager.getAllTemplates();
        System.out.println("删除后所有模板:");
        for (Template t : allTemplates) {
            System.out.println(t);
        }
    }

    private static void testSecondaryIndexOperations(TemplateManager templateManager, TemplateDataOperator dataOperator) throws BTreeException, IOException, ClassNotFoundException {
        // 创建带二级索引的模板
        Template userTemplate = new Template("User");
        Column idCol = new Column("id", "INT", true, false); // 主键列
        Column emailCol = new Column("email", "STRING", false, true, true);
        Column nameCol = new Column("name", "STRING", false, true, true);
        userTemplate.addColumn(idCol);
        userTemplate.addColumn(emailCol);
        userTemplate.addColumn(nameCol);
        long templateId = templateManager.createTemplate(userTemplate);
        System.out.println("创建带二级索引的模板 User，ID: " + templateId);

        // 插入测试数据
        TemplateDataRow row1 = new TemplateDataRow(userTemplate);
        row1.setColumnValue("id", 1001);
        row1.setColumnValue("email", "alice@example.com");
        row1.setColumnValue("name", "alice");
        dataOperator.addData(templateId, row1);

        TemplateDataRow row2 = new TemplateDataRow(userTemplate);
        row2.setColumnValue("id", 1002);
        row2.setColumnValue("email", "bob@example.com");
        row2.setColumnValue("name", "bob");
        dataOperator.addData(templateId, row2);

        TemplateDataRow row3 = new TemplateDataRow(userTemplate);
        row3.setColumnValue("id", 1003);
        row3.setColumnValue("email", "cindy@example.com");
        row3.setColumnValue("name", "cindy");
        dataOperator.addData(templateId, row3);
        System.out.println("数据插入成功");

        // 主键查询测试
        System.out.println("\n=== 主键查询测试 ===");
        TemplateDataRow result1 = dataOperator.getData(templateId, 1001);
        System.out.println("主键1001查询结果: " + result1);
        assert result1 != null : "主键查询失败";

        // 二级索引查询测试
        System.out.println("\n=== 二级索引查询测试 ===");
        List<Value> emailResults = templateManager.queryBySecondaryIndex(templateId, "email", new Value("bob@example.com"));
        System.out.println("邮箱bob@example.com查询结果: " + emailResults);
        assert !emailResults.isEmpty() : "二级索引查询失败";
        Value pkValue = emailResults.get(0);
        System.out.println(pkValue);
        TemplateDataRow result2 = dataOperator.getData(templateId, pkValue);
        System.out.println("关联数据: " + result2);

        List<Value> nameResults = templateManager.queryBySecondaryIndex(templateId, "name", new Value("cindy"));
        System.out.println("姓名cindy查询结果: " + nameResults);
        assert !nameResults.isEmpty() : "二级索引查询失败";
        Value pkValuename = nameResults.get(0);
        System.out.println(pkValuename);
        TemplateDataRow result3 = dataOperator.getData(templateId, pkValuename);
        System.out.println("关联数据: " + result3);

        // 更新数据测试
        System.out.println("\n=== 更新数据测试 ===");
        TemplateDataRow updatedRow = new TemplateDataRow(userTemplate);
        updatedRow.setColumnValue("id", 1001);
        updatedRow.setColumnValue("email", "alice.new@example.com"); // 修改索引列
        updatedRow.setColumnValue("name", "alice");
        dataOperator.updateData(templateId, updatedRow);

        // 验证旧索引删除
        List<Value> oldEmailResults = templateManager.queryBySecondaryIndex(templateId, "email", new Value("alice@example.com"));
        System.out.println("旧邮箱查询结果（应空）: " + oldEmailResults);
        assert oldEmailResults.isEmpty() : "旧索引未删除";

        // 验证新索引添加
        List<Value> newEmailResults = templateManager.queryBySecondaryIndex(templateId, "email", new Value("alice.new@example.com"));
        System.out.println("新邮箱查询结果: " + newEmailResults);
        assert !newEmailResults.isEmpty() : "新索引未添加";
        Value pkValuenew = newEmailResults.get(0);
        System.out.println(pkValuenew);
        TemplateDataRow resultnew = dataOperator.getData(templateId, pkValuenew);
        System.out.println("关联数据: " + resultnew);

        // 主键删除测试
        System.out.println("\n=== 主键删除测试 ===");
        dataOperator.removeData(templateId, 1001);
        TemplateDataRow deletedData = dataOperator.getData(templateId, 1001);
        System.out.println("删除后查询结果（应空）: " + deletedData);
        assert deletedData == null : "主键删除失败";

        // 二级索引删除测试
        System.out.println("\n=== 二级索引email删除测试 ===");
        List<Value> deleteTargets = templateManager.queryBySecondaryIndex(templateId, "email", new Value("bob@example.com"));
        System.out.println(deleteTargets);
        for (Value pk : deleteTargets) {
            dataOperator.removeData(templateId, pk);
        }

        TemplateDataRow deletedData2 = dataOperator.getData(templateId, 1002);
        System.out.println("删除后查询结果（应空）: " + deletedData2);
        assert deletedData2 == null : "二级索引email删除失败";

        System.out.println("\n=== 二级索引name删除测试 ===");
        List<Value> deleteTargetsname = templateManager.queryBySecondaryIndex(templateId, "name", new Value("cindy"));
        System.out.println(deleteTargetsname);
        for (Value pk : deleteTargetsname) {
            dataOperator.removeData(templateId, pk);
        }

        TemplateDataRow deletedData3 = dataOperator.getData(templateId, 1003);
        System.out.println("删除后查询结果（应空）: " + deletedData3);
        assert deletedData3 == null : "二级索引name删除失败";
    }

    // 递归删除测试目录
    private static void deleteDir(File dir) {
        File[] files = dir.listFiles();
        if (files != null) {
            for (File f : files) {
                if (f.isDirectory()) {
                    deleteDir(f);
                } else {
                    f.delete();
                }
            }
        }
        dir.delete();
    }
}